1 module hip.gui.button;
2 import hip.api.graphics.g2d.renderer2d;
3 public import hip.gui.widget;
4 
5 
6 interface IButtonRenderer 
7 {
8     void render(Widget.Bounds worldBounds, Button.State state);
9     static IButtonRenderer DebugButtonRenderer()
10     {
11         __gshared IButtonRenderer dbgRenderer;
12         if(dbgRenderer is null)
13         {
14             dbgRenderer = new class IButtonRenderer
15             {
16                 void render(Widget.Bounds worldBounds, Button.State state) const
17                 {
18                     alias b = worldBounds;
19                     final switch(state) with(Button.State)
20                     {
21                         case idle: fillRoundRect(b.x, b.y, b.width, b.height, 12, HipColor.red);
22                             break;
23                         case hovered: fillRoundRect(b.x, b.y, b.width, b.height, 12, HipColor(255, 127, 0));
24                             break;
25                         case pressed: fillRoundRect(b.x, b.y, b.width, b.height, 12, HipColor(127, 0, 0));
26                             break;
27                     }
28                 }
29             };
30         }
31         return dbgRenderer;
32     }
33 }
34 
35 class SpriteButtonRenderer : IButtonRenderer
36 {
37     IHipTextureRegion idle;
38     IHipTextureRegion hover;
39     IHipTextureRegion pressed;
40 
41 
42     void render(Widget.Bounds worldBounds, Button.State state)
43     {
44         IHipTextureRegion target;
45         final switch ( state )
46         {
47             case Button.state.idle: target = idle; break;
48             case Button.state.hovered: target = hover; break;
49             case Button.state.pressed: target = pressed; break;
50         }
51         drawRegion(target, worldBounds.x, worldBounds.y);
52     }
53 }
54 
55 class Button : Widget
56 {
57     enum State
58     {
59         idle,
60         pressed,
61         hovered,
62     }
63 
64     State state;
65     IButtonRenderer renderer;
66 
67     protected void delegate() onClick;
68     protected void delegate() onHover;
69 
70     this(int x, int y, int w, int h)
71     {
72         setPosition(x,y);
73         width = w;
74         height = h;
75         renderer = IButtonRenderer.DebugButtonRenderer;
76     }
77     void setOnHover(void delegate() onHover)
78     {
79         this.onHover = onHover;
80     }
81     void setOnClick(void delegate() onClick)
82     {
83         this.onClick = onClick;
84     }
85 
86     private bool isMouseInsideButton()
87     {
88         import hip.api;
89         import hip.math.collision;
90         Bounds b = getWorldBounds();
91         float[2] pos = HipInput.getMousePosition();
92         return isPointInRect(pos[0], pos[1], b.x, b.y, b.width, b.height);
93     }
94 
95     override void onMouseEnter()
96     {
97         if(onHover) onHover();
98         state = State.hovered;
99     }
100     override void onMouseDown()
101     {
102         state = State.pressed;
103     }
104     override void onMouseUp()
105     {
106         if(state == State.pressed && onClick) onClick();
107         state = State.idle;
108     }
109     override void onMouseExit()
110     {
111         if(state != State.pressed)
112             state = State.idle;
113     }
114 
115     void setButtonRenderer(IButtonRenderer renderer)
116     {
117         this.renderer = renderer;
118     }
119     override void onRender()
120     {
121         import hip.api;
122         renderer.render(Bounds(worldTransform.x, worldTransform.y, width, height), state);
123     }
124 }